﻿using UnityEngine;
using UnityEditor;
using System.IO;

namespace JinndevEditor {

    public static class CommonEditorUtil {

        public static bool SetReadable(Texture2D texture, bool isReadable) {
            if (texture == null) {
                return false;
            }
            string path = AssetDatabase.GetAssetPath(texture);
            TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
            bool originValue = importer.isReadable;
            importer.isReadable = isReadable;
            importer.SaveAndReimport();
            return originValue;
        }

        public static bool SetPixel(Texture2D inputTexture, int x, int y, ColorChannel inputChannel, ColorChannel outputChannel, bool reverse, ref Color color) {
            Color inputColor = inputTexture == null ? new Color(1, 1, 1, 1) : inputTexture.GetPixel(x, y);
            switch (inputChannel) {
                case ColorChannel.R:
                    SetChannel(outputChannel, reverse ? (1 - inputColor.r) : inputColor.r, ref color);
                    break;
                case ColorChannel.G:
                    SetChannel(outputChannel, reverse ? (1 - inputColor.g) : inputColor.g, ref color);
                    break;
                case ColorChannel.B:
                    SetChannel(outputChannel, reverse ? (1 - inputColor.b) : inputColor.b, ref color);
                    break;
                case ColorChannel.A:
                    SetChannel(outputChannel, reverse ? (1 - inputColor.a) : inputColor.a, ref color);
                    break;
            }
            return true;
        }

        public static void SetChannel(ColorChannel channel, float value, ref Color color) {
            switch (channel) {
                case ColorChannel.R:
                    color.r = value;
                    break;
                case ColorChannel.G:
                    color.g = value;
                    break;
                case ColorChannel.B:
                    color.b = value;
                    break;
                case ColorChannel.A:
                    color.a = value;
                    break;
            }
        }

        public static T GetFirstNonNull<T>(params T[] objects) where T : Object {
            if (objects != null) {
                foreach (T obj in objects) {
                    if (obj != null) {
                        return obj;
                    }
                }
            }
            return null;
        }

        public static string GetDir(params Object[] objects) {
            if (objects != null) {
                foreach (Object obj in objects) {
                    if (obj != null) {
                        string path = AssetDatabase.GetAssetPath(obj);
                        return Path.Combine(Application.dataPath, Path.GetDirectoryName(path).Substring("Assets/".Length));
                    }
                }
            }
            return Application.dataPath;
        }

        public static string GetPrefix(params Object[] objects) {
            if (objects == null) {
                return null;
            }
            foreach (Object obj in objects) {
                if (obj != null) {
                    string name = obj.name;
                    if (name.Contains("_")) {
                        name = name.Substring(0, name.LastIndexOf("_"));
                        return name;
                    }
                }
            }
            return null;
        }

        public static void SaveTexture(Texture2D texture, string dir, string fileName) {
            SaveTexture(texture, Path.Combine(dir, fileName));
        }

        public static void SaveTexture(Texture2D texture, string filePath) {
            byte[] bytes;
            if (filePath.EndsWith("tga")) {
                bytes = texture.EncodeToTGA();
            }
            else if (filePath.EndsWith("jpg")) {
                bytes = texture.EncodeToJPG();
            }
            else {
                bytes = texture.EncodeToPNG();
            }
            File.WriteAllBytes(filePath, bytes);
            AssetDatabase.Refresh();
        }


        /// <summary>
        /// 另存Sprite为图片
        /// </summary>
        /// <param name="sprite"></param>
        public static void SaveTexture(Sprite sprite) {
            Rect rect = sprite.rect;

            Texture2D texture = new Texture2D((int)rect.width, (int)rect.height);
            texture.filterMode = FilterMode.Point;

            Color[] colors = sprite.texture.GetPixels((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
            texture.SetPixels(colors);

            texture.Apply(false, false);

            string dir = Path.GetDirectoryName(AssetDatabase.GetAssetPath(sprite));
            SaveTexture(texture, dir, texture.name + ".png");
        }

        public static string AssetPathToFilePath(string assetPath) {
            if (assetPath == null || !assetPath.StartsWith("Assets")) {
                return assetPath;
            }
            return Application.dataPath + assetPath.Substring("Assets".Length);
        }

        public static string FilePathToAssetPath(string filePath) {
            if (filePath == null || filePath.StartsWith("Assets")) {
                return filePath;
            }
            return "Assets" + filePath.Substring(Application.dataPath.Length);
        }

        /// <summary>
        /// 动画删减帧
        /// </summary>
        /// <param name="clip"></param>
        /// <param name="keyName">"localscale","localrotation"</param>
        public static void ReduceScaleKey(AnimationClip clip, string keyName) {
            EditorCurveBinding[] curves = AnimationUtility.GetCurveBindings(clip);

            for (int j = 0; j < curves.Length; j++) {
                EditorCurveBinding curveBinding = curves[j];

                if (curveBinding.propertyName.ToLower().Contains(keyName)) {
                    AnimationUtility.SetEditorCurve(clip, curveBinding, null);
                }
            }
        }

        /// <summary>
        /// 动画精度压缩
        /// </summary>
        public static void ReduceFloatPrecision(AnimationClip clip) {
            EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(clip);

            for (int j = 0; j < bindings.Length; j++) {
                EditorCurveBinding curveBinding = bindings[j];
                AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, curveBinding);

                if (curve == null || curve.keys == null) {
                    continue;
                }

                Keyframe[] keys = curve.keys;
                for (int k = 0; k < keys.Length; k++) {
                    Keyframe key = keys[k];
                    key.value = float.Parse(key.value.ToString("f3"));
                    key.inTangent = float.Parse(key.inTangent.ToString("f3"));
                    key.outTangent = float.Parse(key.outTangent.ToString("f3"));
                    keys[k] = key;
                }
                curve.keys = keys;

                AnimationUtility.SetEditorCurve(clip, curveBinding, curve);
            }
        }

    }

}
